Powertools for AWS Lambda (TypeScript) を使って DynamoDB テーブルからのデータ取得をキャッシュしてみた
こんにちは、CX事業本部 Delivery部の若槻です。
以前に Powertools for AWS Lambda (TypeScript) を使って AWS Systems Manager Parameter Store からのデータ取得のキャッシュを試してみました。
この Powertools ですが、DynamoDB にも対応しており、パラメーター保管領域として使用しているテーブルからのデータ取得のキャッシュを容易に実装することもできます。
試してみた
Powertools for AWS Lambda (TypeScript) を使って DynamoDB からのデータ取得のキャッシュを試してみます。
インストール
必要なモジュールをインストールします。
npm install @aws-lambda-powertools/parameters @aws-sdk/client-dynamodb @aws-sdk/util-dynamodb
検証環境の作成
検証環境として、DynamoDB テーブル 3 つおよび Lambda 関数および AWS CDK で作成します。
import { aws_dynamodb, aws_lambda_nodejs, aws_lambda, RemovalPolicy, Stack, StackProps, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class CdkSampleStack extends Stack { public readonly myFileObjectKey: string; constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // my-table:PK=id const myTable = new aws_dynamodb.Table(this, 'myTable', { tableName: 'my-table', partitionKey: { name: 'id', type: aws_dynamodb.AttributeType.STRING }, billingMode: aws_dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: RemovalPolicy.DESTROY, }); // my-table2:PK=id, SK=sk const myTable2 = new aws_dynamodb.Table(this, 'myTable2', { tableName: 'my-table2', partitionKey: { name: 'id', type: aws_dynamodb.AttributeType.STRING }, sortKey: { name: 'sk', type: aws_dynamodb.AttributeType.STRING }, billingMode: aws_dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: RemovalPolicy.DESTROY, }); // my-table3:PK=customId, SK=customSk const myTable3 = new aws_dynamodb.Table(this, 'my-table3', { tableName: 'my-table3', partitionKey: { name: 'customId', type: aws_dynamodb.AttributeType.STRING, }, sortKey: { name: 'customSk', type: aws_dynamodb.AttributeType.STRING }, billingMode: aws_dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: RemovalPolicy.DESTROY, }); // Lambda 関数 const myFunction = new aws_lambda_nodejs.NodejsFunction( this, 'myFunction', { functionName: 'myFunction', architecture: aws_lambda.Architecture.ARM_64, runtime: aws_lambda.Runtime.NODEJS_18_X, } ); // 読み取り権限付与 myTable.grantReadData(myFunction); myTable2.grantReadData(myFunction); myTable3.grantReadData(myFunction); } }
パラメーター取得(キャッシュなし)
my-table:PK=id
からのパラメーター取得です。既定では PK は id
というキー名である必要があります。dynamoDBProvider を構成し、get
メソッドを使用することによりパラメーターを取得します。
import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb'; const dynamoDBProvider = new DynamoDBProvider({ tableName: 'my-table' }); export const handler = async (): Promise<any> => { const value = await dynamoDBProvider.get('my-parameter'); return value; };
my-table に id: my-parameter
のアイテムを作成します。ここでパラメーターの値としたい属性名を value
とする必要があります。
aws dynamodb put-item \ --table-name my-table \ --item '{"id": {"S": "my-parameter"}, "value": {"S": "my-value"}}'
Lambda 関数を実行すると値が取得されました。
$ aws lambda invoke --function-name myFunction response.json $ cat response.json "my-value"
ここで、get
は既定ではキャッシュ期間は 0 なので、変更後の値はすぐに取得されます。
id: my-parameter
のアイテムの value
属性の値を更新します。
$ aws dynamodb put-item \ --table-name my-table \ --item '{"id": {"S": "my-parameter"}, "value": {"S": "new-my-value"}}'
Lambda 関数を実行すると更新後の値が取得されました。
$ aws lambda invoke --function-name myFunction response.json $ cat response.json "new-my-value"
パラメーター取得(キャッシュあり)
続いて先程と同じテーブルでキャッシュを有効にしてパラメーター取得を行います。get
メソッドで maxAge
を指定することによりキャッシュ期間を設定します。
import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb'; const dynamoDBProvider = new DynamoDBProvider({ tableName: 'my-table' }); export const handler = async (): Promise<any> => { const value = await dynamoDBProvider.get('my-parameter', { maxAge: 60 }); return value; };
my-table に id: my-parameter
のアイテムを作成します。
aws dynamodb put-item \ --table-name my-table \ --item '{"id": {"S": "my-parameter"}, "value": {"S": "my-value"}}'
Lambda 関数を実行すると値が取得されました。
$ aws lambda invoke --function-name myFunction response.json;cat response.json "my-value"
ここで値を更新します。
id: my-parameter
のアイテムの value
属性の値を更新します。
$ aws dynamodb put-item \ --table-name my-table \ --item '{"id": {"S": "my-parameter"}, "value": {"S": "new-my-value"}}'
前回 Lambda 関数実行から 60秒(キャッシュ期間)以内に再度実行すると、更新前の値が取得されました。キャッシュが働いていますね。
$ aws lambda invoke --function-name myFunction response.json;cat response.json "my-value"
60秒(キャッシュ期間)経過後に再度実行すると、更新後の値が取得されました。キャッシュがクリアされています。
$ aws lambda invoke --function-name myFunction response.json;cat response.json "new-my-value"
複数のパラメーター取得
my-table2:PK=id, SK=sk
からのパラメーター取得です。既定では PK は id
、SK は sk
というキー名である必要があります。dynamoDBProvider を構成し、getMultiple
メソッドを使用することにより複数のパラメーターをクエリにより取得します。
import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb'; const dynamoDBProvider = new DynamoDBProvider({ tableName: 'my-table2' }); export const handler = async (): Promise<any> => { const values = await dynamoDBProvider.getMultiple('my-hash-key'); return values; };
ハッシュキー id: my-hash-key
に対して複数のアイテムを作成します。get
と同様にパラメーターの値としたい属性名を value
とする必要があります。
aws dynamodb put-item \ --table-name my-table2 \ --item '{"id": {"S": "my-hash-key"}, "sk": {"S": "param-a"}, "value": {"S": "my-value-a"}}' aws dynamodb put-item \ --table-name my-table2 \ --item '{"id": {"S": "my-hash-key"}, "sk": {"S": "param-b"}, "value": {"S": "my-value-b"}}' aws dynamodb put-item \ --table-name my-table2 \ --item '{"id": {"S": "my-hash-key"}, "sk": {"S": "param-c"}, "value": {"S": "my-value-c"}}'
Lambda 関数を実行すると、指定したハッシュキーに対応する複数の値が取得されました。
$ aws lambda invoke --function-name myFunction response.json;cat response.json {"param-a":"my-value-a","param-b":"my-value-b","param-c":"my-value-c"}
カスタマイズしたパラメーターの取得
続いて、my-table3:PK=customId, SK=customSk
からのパラメーター取得です。DynamoDBProvider
でオプションを指定することにより、PK、SK、値の属性名をカスタマイズすることができます。
import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb'; const dynamoDBProvider = new DynamoDBProvider({ tableName: 'my-table3', keyAttr: 'customId', sortAttr: 'customSk', valueAttr: 'count', }); export const handler = async (): Promise<any> => { const values = await dynamoDBProvider.getMultiple('my-hash-key'); return values; };
ハッシュキー customId: my-hash-key
に対して、DynamoDBProvider
で指定した属性名でアイテムを作成します。
aws dynamodb put-item \ --table-name my-table3 \ --item '{"customId": {"S": "my-hash-key"}, "customSk": {"S": "param-a"}, "count": {"N": "1"}}' aws dynamodb put-item \ --table-name my-table3 \ --item '{"customId": {"S": "my-hash-key"}, "customSk": {"S": "param-b"}, "count": {"N": "2"}}' aws dynamodb put-item \ --table-name my-table3 \ --item '{"customId": {"S": "my-hash-key"}, "customSk": {"S": "param-c"}, "count": {"N": "3"}}'
Lambda 関数を実行すると、指定したソートキーの値をキー、属性名を値として結果が取得されました。
$ aws lambda invoke --function-name myFunction response.json;cat response.json {"param-a":1,"param-b":2,"param-c":3}
おわりに
Powertools for AWS Lambda (TypeScript) を使って DynamoDB テーブルからのデータ取得をキャッシュしてみました。
ユースケースは限られそうですが、DynamoDB テーブルを単一のキー/バリューのみのデータ格納領域として使用するのであれば、選択肢としてありではないでしょうか。
以上